package main

import (
	"fmt"
	"math"
	"sort"
	"time"
)

// 定义结构体
// 长方形
type Rectangle struct {
	length float64
	width  float64
}

// 圆形
type Circle struct {
	radius float64
}

// 三角形
type Triangle struct {
	baseLen float64
	height  float64
}

// 计算几何图形面积
// 求长方形面积
func (r *Rectangle) calArea() float64 {
	return r.length * r.width
}

// 求圆形面积
func (c *Circle) calArea() float64 {
	return math.Pi * float64(math.Pow(c.radius, 2))
}

//求三角形面积

func (t *Triangle) calArea() float64 {
	return (t.baseLen * t.height) / 2
}

// 构造函数

// 长方形
func NewRectangle() *Rectangle {
	fmt.Println("长方形构造完成,默认：长=2,宽=1")
	return &Rectangle{2, 1}
}

// 圆形,默认：半径2
func NewCircle() *Circle {
	fmt.Println("圆形构造完成，默认：半径=2")
	return &Circle{2}
}

// 三角形,默认：底 1，高2
func NewTriangle() *Triangle {
	fmt.Println("三角形构造完成，默认：底=1，高=2")
	return &Triangle{1, 2}
}

type CalArea interface {
	calArea() float64
}

//格式化输出结构体

// 长方形格式化输出
func (r *Rectangle) String() string {
	return fmt.Sprintf("长方面积:%.2f", r.calArea())
}

// 圆形格式化输出
func (c *Circle) String() string {
	return fmt.Sprintf("圆形:%.2f", c.calArea())
}

// 三角形格式化输出
func (t *Triangle) String() string {
	return fmt.Sprintf("三角面积:%.2f", t.calArea())

}

// 斐波那契数列递归版本增加缓存

func fib(n int, f map[int]int) int {
	if n < 3 {
		return 1
	}
	// return fib(n-1, f) + fib(n-2, f)
	return queryFibValue(n-1, f) + queryFibValue(n-2, f)
}

// 查询斐波那契数列缓存
func queryFibValue(n int, f map[int]int) int {
	if v, ok := f[n]; ok {
		return v
	}
	return fib(n, f)
}

func main() {
	//第一题：求面积
	r := NewRectangle()
	fmt.Printf("长方形宽:%.2f,高:%.2f,面积:%.2f\n", r.length, r.width, r.calArea())
	c := NewCircle()
	fmt.Printf("圆形宽度：%.2f ,面积:%.2f\n", c.radius, c.calArea())
	t := NewTriangle()
	fmt.Printf("三角形底:%.2f,高:%.2f,面积：%.2f\n", t.baseLen, t.height, t.calArea())

	//第二题：排序
	fmt.Println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
	//修改几个实例的参数
	r.length = 5
	c.radius = 8
	t.baseLen = 6.3

	var a = []CalArea{r, c, t}
	fmt.Printf("%v\n", a) //排序前打印当前切片

	sort.Slice(a, func(i, j int) bool {
		return a[i].calArea() > a[j].calArea()
	})
	fmt.Printf("%v\n", a)

	//第三题：打印斐波那契数列,已增加缓存，查询99个斐波那契数列
	// var fibCacheMap = map[int]int{}
	var fibCacheMap = make(map[int]int, 100)
	for i := 1; i < 20; i++ {

		r := fib(i, fibCacheMap)
		fibCacheMap[i] = r
	}
	fmt.Println(fibCacheMap)

	//第四题：8年前的今天上午9点30分
	fmt.Println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
	var tm = time.Now()
	//计算8年前的时间
	tm = tm.AddDate(-8, 0, 0)
	tm = time.Date(tm.Year(), tm.Month(), tm.Day(), 9, 30, 0, 0, tm.Location())
	fmt.Printf("8年前的今天上午9:30分是：%v\n", tm)
	fmt.Printf("毫秒时间戳是：%v\n", tm.UnixMilli())
	y, d := tm.ISOWeek()

	fmt.Printf("%v的%d月%d日是%v,本年已经过了%v周\n", y, tm.Month(), tm.Day(), tm.Weekday(), d)

	dela := time.Now().Sub(tm)
	fmt.Printf("距离今天已经过了%.f天\n", math.Ceil(dela.Hours()/24))
}
